package com.lmy.androidcustomview.touch.drag

import android.content.Context
import android.os.Build
import android.util.AttributeSet
import android.view.MotionEvent
import android.view.View
import android.view.ViewGroup
import androidx.annotation.RequiresApi
import androidx.core.view.ViewCompat
import androidx.core.view.children
import androidx.customview.widget.ViewDragHelper


/**
 * @author lmy
 * @功能: 网格布局
 * @Creat 2/15/21 1:18 PM
 * @Compony 465008238@qq.com
 */

class DragHelperGridView(context: Context?, attrs: AttributeSet?) : ViewGroup(context, attrs) {
    //ViewDragHelper是用于编写自定义ViewGroup的实用程序类。
    // 它提供了许多有用的操作和状态跟踪，以允许用户在其父级ViewGroup中拖动和重新放置视图。
    private var dragHelper = ViewDragHelper.create(this, DragCallback())

    //定义横向和纵向的列数
    private val COLUMNS = 2
    private val ROWS = 3
    override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
        /**
         * 测量View修正后的宽高
         * 计算子View的宽度和高度 并测量
         */
        val specWidth = MeasureSpec.getSize(widthMeasureSpec)
        val specHeight = MeasureSpec.getSize(heightMeasureSpec)
        val childWidth = specWidth / COLUMNS
        val childHeight = specHeight / ROWS
        measureChildren(
            MeasureSpec.makeMeasureSpec(childWidth, MeasureSpec.EXACTLY),
            MeasureSpec.makeMeasureSpec(childHeight, MeasureSpec.EXACTLY)
        )
        setMeasuredDimension(specWidth, specHeight)
    }

    override fun onLayout(changed: Boolean, l: Int, t: Int, r: Int, b: Int) {
        var childLeft: Int
        var childTop: Int
        val childWidth = width / COLUMNS
        val childHeight = height / ROWS
        /**
         * 遍历子View并设置子View的位置
         * 因为我们横向只有两列 横向偏移距离=index%2*子view的宽度  只可能是0或者1
         * 纵向就需要index/2*子view的宽度
         */
        for ((index, child) in children.withIndex()) {
            childLeft = index % 2 * childWidth
            childTop = index / 2 * childHeight
            //设置子View的布局
            child.layout(childLeft, childTop, childLeft + childWidth, childTop + childHeight)
        }
    }

    /**
     *使用dragHelper接管onInterceptTouchEvent
     */
    override fun onInterceptTouchEvent(ev: MotionEvent): Boolean {
        return dragHelper.shouldInterceptTouchEvent(ev)
    }

    /**
     *使用dragHelper接管onTouchEvent
     */
    override fun onTouchEvent(event: MotionEvent): Boolean {
        dragHelper.processTouchEvent(event)
        return true
    }

    /**
     *dragHelper计算工作借宿才不重绘界面
     */
    override fun computeScroll() {
        if (dragHelper.continueSettling(true)) {
            ViewCompat.postInvalidateOnAnimation(this)
        }
    }

    /**
     *自定义继承iewDragHelper.Callback()类
     */
    private inner class DragCallback : ViewDragHelper.Callback() {
        var capturedLeft = 0f
        var capturedTop = 0f

        /**
         * 必须实现的 是不是接触View就开始拖拽
         * 试着抓住View
         */
        override fun tryCaptureView(child: View, pointerId: Int): Boolean {
            return true
        }

        /**
         * 返回手指滑动的偏移量 返回left表示横向滑动的距离不作修正
         * 直接返回0表示偏移量为0 横向不能拖拽
         */
        override fun clampViewPositionHorizontal(child: View, left: Int, dx: Int): Int {
            return left
        }

        /**
         * 返回手指滑动的偏移量 返回left表示横向滑动的距离不作修正
         * 直接返回0表示偏移量为0 纵向不能拖拽
         */
        override fun clampViewPositionVertical(child: View, top: Int, dy: Int): Int {
            return top
        }


        /**
         *当View被拖起来的时候
         */
        @RequiresApi(Build.VERSION_CODES.LOLLIPOP)
        override fun onViewCaptured(capturedChild: View, activePointerId: Int) {
            capturedChild.elevation = elevation + 1
            capturedLeft = capturedChild.left.toFloat()
            capturedTop = capturedChild.top.toFloat()
        }

        /**
         *当View坐标改变的时候会被调用
         */
        override fun onViewPositionChanged(
            changedView: View,
            left: Int,
            top: Int,
            dx: Int,
            dy: Int
        ) {
        }

        /**
         *当松手View以后触发
         */
        override fun onViewReleased(releasedChild: View, xvel: Float, yvel: Float) {
            //开始计算 然后重绘界面
            dragHelper.settleCapturedViewAt(capturedLeft.toInt(), capturedTop.toInt())
            postInvalidateOnAnimation()
        }
    }
}
